local gamelib = require "club.threecard.gamelib"
local Vector3 = CS.UnityEngine.Vector3
local Ease = CS.DG.Tweening.Ease
local BlazeNS = CS.Blaze
local GameObjectExtension = BlazeNS.GameObjectExtension

local page_panel = gamelib.ui.element()

local default_res = "club.threecard.gamelib/ui/widgets.b:page_panel"

local space = 800;
local time = 0.25;

function page_panel:ctor(pages, title, banker, bg, res)
    self.title = title or "title未设置";
    self.banker_url = banker;
    self.bg_url = bg;
    self.current_index = 0;
    self.pages = pages;
    self.res = res or default_res;
    self.is_ok = false;
    self.indexes = {};
end

local index = 
{
    new = function(obj)
        local t = {}
        t.gameObject = obj;
        t.transform = obj.transform;
        t.selected = obj.transform:Find("selected").gameObject;
        t.unselected = obj.transform:Find("unselected").gameObject;

        t.selected:SetActive(false);
        t.unselected:SetActive(true);
        return t;
    end
}

local function wait_other_pages(self)
    self.co = gamelib.coroutine.start(function()
        local left_count = #self.pages;
        while left_count > 0 do
            local c = #self.pages;
            for _, page in ipairs(self.pages) do
                if page.loaded then
                    c = c - 1;
                end
            end
            left_count = c;
            gamelib.coroutine.step();
        end

        self:all_load_over();
    end)
end

function page_panel:load()
    self:super("load");
    for _, page in ipairs(self.pages) do
        page:load();
        page:set_parent(self.pages_hide_root, false)
    end

    if self.banker_url then
        local is_ok, result = app.res.load(self.banker_url);
        if is_ok then
            self.banker.sprite = result;
        end
    end

    if self.bg_url then
        local is_ok, result = app.res.load(self.bg_url);
        if is_ok then
            self.pages_bg.sprite = result;
        end
    end

    wait_other_pages(self);
end

function page_panel:all_load_over()
    self.is_ok = true;
    self.current_index = 1;
    self.pages[self.current_index]:set_parent(self.pages_root, false);
    self.co = nil;
    self.title_txt.text = self.title;

    self:init_index();
    self:update_index();
    self:update_subhead();
end

function page_panel:init_index()
    for i = 1, #self.pages do
        local obj = GameObjectExtension.GetFromPool(self.index_node);
        local i = index.new(obj);
        i.transform:SetParent(self.index_grid, false);
        table.insert(self.indexes, i);
    end
end

function page_panel:update_index()
    for i, index in ipairs(self.indexes) do
        index.selected:SetActive(self.current_index == i);
        index.unselected:SetActive(self.current_index ~= i);
    end
end

function page_panel:update_subhead()
    self.subhead_txt.text = self.pages[self.current_index].title or "";
end

function page_panel:on_injected(bind)
    bind("button.click", self.btn_confirm, self.confirm_ivk);
    bind("button.click", self.btn_left, self.left_ivk);
    bind("button.click", self.btn_right, self.right_ivk);

    gamelib.utility.button_style.highlight_scale(self.btn_confirm);
    gamelib.utility.button_style.highlight_scale(self.btn_left);
    gamelib.utility.button_style.highlight_scale(self.btn_right);
end

function page_panel:confirm_ivk()
    self:hide();
end

local function change_index(self, old, dir)
    local current_page = self.pages[self.current_index];
    local last_page = self.pages[old];

    local to_pos = last_page.transform.localPosition;

    local start_pos = Vector3(to_pos.x - dir * space, to_pos.y, to_pos.z);
    current_page:set_parent(self.pages_root, false);
    current_page.transform.localPosition = start_pos;
    current_page.transform:DOLocalMove(to_pos, time)
    :SetEase(Ease.Linear)
    
    to_pos = Vector3(last_page.transform.localPosition.x + space * dir, last_page.transform.localPosition.y, last_page.transform.localPosition.z);
    last_page.transform:DOLocalMove(to_pos, time)
    :SetEase(Ease.Linear)
    :OnComplete(function()
        last_page:set_parent(self.pages_hide_root, false);
        self:update_index();
        self:update_subhead();
    end)
end

function page_panel:left_ivk()
    if #self.pages == 0 or #self.pages == 1 then
        return;
    end

    local old = self.current_index;
    self.current_index = self.current_index - 1;
    if self.current_index < 1 then
        self.current_index = #self.pages;
    end

    change_index(self, old, -1);
end

function page_panel:right_ivk()
    if #self.pages == 0 or #self.pages == 1 then
        return;
    end

    local old = self.current_index;
    self.current_index = self.current_index + 1;
    if self.current_index > #self.pages then
        self.current_index = 1;
    end

    change_index(self, old, 1);
end

function page_panel:on_release()
    if self.co then
        gamelib.coroutine.stop(self.co);
        self.co = nil;
    end
    self.is_ok = false;

    for _, page in ipairs(self.pages) do
        page:release();
    end
    self:super("on_release");
end

return page_panel